home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung / Power-Programmierung (Tewi)(1994).iso / magazine / nan_news / toolkit / tmenu.asm < prev    next >
Assembly Source File  |  1991-08-15  |  39KB  |  748 lines

  1. ; File......: TMENU.ASM
  2. ; Author....: Ted Means
  3. ; Date......: $Date:   15 Aug 1991 23:07:14  $
  4. ; Revision..: $Revision:   1.2  $
  5. ; Log file..: $Logfile:   E:/nanfor/src/tmenu.asv  $
  6. ; This is an original work by Ted Means and is placed in the
  7. ; public domain.
  8. ;
  9. ; Modification history:
  10. ; ---------------------
  11. ;
  12. ; $Log:   E:/nanfor/src/tmenu.asv  $
  13. ;  
  14. ;     Rev 1.2   15 Aug 1991 23:07:14   GLENN
  15. ;  Forest Belt proofread/edited/cleaned up doc
  16. ;  
  17. ;     Rev 1.1   14 Jun 1991 19:55:00   GLENN
  18. ;  Minor edit to file header
  19. ;  
  20. ;     Rev 1.0   01 Apr 1991 01:03:56   GLENN
  21. ;  Nanforum Toolkit
  22. ;  
  23.  
  24. ; This source code is used by Toolkit sources ATPROMPT.PRG and 
  25. ; MENUTO.PRG.  Look at that code for details on the TMENU system.
  26.  
  27. ; This code depends on "TMENU.INC"
  28. ;
  29.  
  30.         IDEAL
  31.  
  32. Public   __ftprompt, __ftmenuto
  33.  
  34. Include  "TMENU.INC"
  35.  
  36. Extrn    __ParInfa:Far
  37. Extrn    __ParCLen:Far
  38. Extrn    __ParC:Far
  39. Extrn    __ParNI:Far
  40. Extrn    __RetNL:Far
  41. Extrn    __Ret:Far
  42. Extrn    __XGrab:Far
  43. Extrn    __XFree:Far
  44. Extrn    __XUnlock:Far
  45.  
  46. Segment  _MenuData Word      "DATA"
  47.  
  48. PrCount  DW        0
  49.  
  50. Label    HeadPtr   DWord                     ; Pointer to head of linked list
  51. HeadOfs  DW        0                         ; of menu items
  52. HeadSeg  DW        0
  53.  
  54. Ends     _MenuData
  55.  
  56.  
  57. Segment  _NanFor   Word      "CODE"
  58.          Assume    CS:_NanFor,ES:_MenuData
  59.  
  60. Proc     __ftprompt Far
  61.  
  62. NewItem: Mov       AX,42                     ; Specify size of menu item
  63.          Push      AX                        ; Put on stack
  64.          Call      __XGrab                   ; Allocate RAM for it
  65.          Add       SP,2                      ; Realign stack
  66.  
  67.          Mov       BX,_MenuData              ; Load local data segment
  68.          Mov       ES,BX                     ; Now put it in a segment reg
  69.          Inc       [ES:PrCount]              ; Increment prompt counter
  70.          Push      [ES:PrCount]              ; We'll need it later
  71.  
  72.          XChg      AX,[ES:HeadOfs]           ; Swap offsets
  73.          XChg      DX,[ES:HeadSeg]           ; Swap segments
  74.          LES       BX,[ES:HeadPtr]           ; Get pointer to new item
  75.          Mov       [MenuItem.NextOfs],AX     ; Move old head pointer to newly
  76.          Mov       [MenuItem.NextSeg],DX     ; allocated menu item
  77.  
  78. GetInfo: Pop       [MenuItem.PrNum]          ; Get prompt counter back
  79.          Push      BP                        ; Save BP
  80.          Mov       BP,SP                     ; Set up stack reference
  81.          Sub       SP,4                      ; Allocate local storage
  82.          Mov       [NodeOfs],BX              ; Save pointer in ES:BX in local
  83.          Mov       [NodeSeg],ES              ; storage -- avoids constant
  84.                                              ; pushing and popping
  85.  
  86.          Mov       AX,1                      ; Specify first parameter
  87.          Push      AX                        ; Put on stack
  88.          Call      __ParNI                   ; Get prompt location
  89.          Add       SP,2                      ; Realign stack
  90.          LES       BX,[NodePtr]              ; Restore node pointer
  91.          Mov       [MenuItem.PrLoc],AX       ; Store prompt location
  92.  
  93.          Mov       AX,2                      ; Specify second parameter
  94.          Push      AX                        ; Put on stack
  95.          Call      __ParClen                 ; Get length
  96.          Add       SP,2                      ; Realign stack
  97.  
  98.          Push      AX                        ; Put length on stack
  99.          Call      __XGrab                   ; Allocate RAM for copy
  100.          Push      DX                        ; Put copy pointer on stack for
  101.          Push      AX                        ; call to _ftStrDup
  102.  
  103.          Mov       AX,2                      ; Specify second parmeter
  104.          Push      AX                        ; Put on stack
  105.          Call      __ParC                    ; Get pointer to prompt
  106.          Add       SP,2                      ; Realign stack
  107.          Push      DX                        ; Put prompt pointer on stack
  108.          Push      AX                        ; for call to _ftStrDup
  109.  
  110.          Call      _ftStrDup                 ; Copy the prompt string
  111.          Add       SP,4                      ; Realign stack
  112.          LES       BX,[NodePtr]              ; Restore node pointer
  113.          Pop       [MenuItem.PrOfs]          ; Store prompt offset
  114.          Pop       [MenuItem.PrSeg]          ; Store prompt offset
  115.          Pop       [MenuItem.PrLen]          ; Store prompt length
  116.          Call      __XUnlock                 ; Tell VMM it's okay to let go
  117.  
  118.          Mov       AX,3                      ; Specify third parmeter
  119.          Push      AX                        ; Put on stack
  120.          Call      __ParNI                   ; Get prompt attribute
  121.          Add       SP,2                      ; Realign stack
  122.          LES       BX,[NodePtr]              ; Restore node pointer
  123.          Mov       [MenuItem.PrAtt],AL       ; Store attribute
  124.  
  125.          Mov       AX,4                      ; Specify fourth parameter
  126.          Push      AX                        ; Put on stack
  127.          Call      __ParNI                   ; Get message location
  128.          Add       SP,2                      ; Realign stack
  129.          LES       BX,[NodePtr]              ; Restore node pointer
  130.          Mov       [MenuItem.MsgLoc],AX      ; Store location
  131.  
  132.          Mov       AX,5                      ; Specify fifth parameter
  133.          Push      AX                        ; Put on stack
  134.          Call      __ParClen                 ; Get length
  135.          Add       SP,2                      ; Realign stack
  136.  
  137.          Push      AX                        ; Put length on stack
  138.          Call      __XGrab                   ; Allocate RAM for copy
  139.          Push      DX                        ; Put copy pointer on stack for
  140.          Push      AX                        ; call to _ftStrDup
  141.  
  142.          Mov       AX,5                      ; Specify fifth parmeter
  143.          Push      AX                        ; Put on stack
  144.          Call      __ParC                    ; Get pointer to message
  145.          Add       SP,2                      ; Realign stack
  146.          Push      DX                        ; Put message pointer on stack
  147.          Push      AX                        ; for call to _ftStrDup
  148.  
  149.          Call      _ftStrDup                 ; Copy the prompt string
  150.          Add       SP,4                      ; Realign stack
  151.          LES       BX,[NodePtr]              ; Restore node pointer
  152.          Pop       [MenuItem.MsgOfs]         ; Store message offset
  153.          Pop       [MenuItem.MsgSeg]         ; Store message segment
  154.          Pop       [MenuItem.MsgLen]         ; Store message length
  155.          Call      __XUnlock                 ; Tell VMM it's okay to let go
  156.          LES       BX,[NodePtr]              ; Restore node pointer
  157.  
  158.          Mov       AX,[MenuItem.MsgLen]      ; Get message length
  159.          SHL       AX,1                      ; Multiply by two
  160.          Push      AX                        ; Put buffer size on stack
  161.          Call      __XGrab                   ; Allocate buffer
  162.          Add       SP,2                      ; Realign stack
  163.          LES       BX,[NodePtr]              ; Restore node pointer
  164.          Mov       [MenuItem.BufOfs],AX      ; Store buffer offset
  165.          Mov       [MenuItem.BufSeg],DX      ; Store buffer segment
  166.  
  167.          Mov       AX,6                      ; Specify sixth parmeter
  168.          Push      AX                        ; Put on stack
  169.          Call      __ParNI                   ; Get message attribute
  170.          Add       SP,2                      ; Realign stack
  171.          LES       BX,[NodePtr]              ; Restore node pointer
  172.          Mov       [MenuItem.MsgAtt],AL      ; Store attribute
  173.  
  174.          Mov       AX,7                      ; Specify seventh parameter
  175.          Push      AX                        ; Save on stack
  176.          Call      __ParNI                   ; Get hotkey attribute
  177.          Add       SP,2                      ; Realign stack
  178.          LES       BX,[NodePtr]              ; Restore node pointer
  179.          Mov       [MenuItem.HKeyAtt],AL     ; Store hotkey attribute
  180.  
  181.          Mov       AX,8                      ; Specify eighth parameter
  182.          Push      AX                        ; Save on stack
  183.          Call      __ParNI                   ; Get hotkey location
  184.          Add       SP,2                      ; Realign stack
  185.          LES       BX,[NodePtr]              ; Restore node pointer
  186.          Mov       [MenuItem.HKeyLoc],AX     ; Store hotkey location
  187.  
  188.          Mov       AX,9                      ; Specify ninth parameter
  189.          Push      AX                        ; Save on stack
  190.          Call      __ParNI                   ; Get light bar attribute
  191.          Add       SP,2                      ; Realign stack
  192.          LES       BX,[NodePtr]              ; Restore node pointer
  193.          Mov       [MenuItem.HKeyVal],AL     ; Store hotkey value
  194.  
  195.          Mov       AX,10                     ; Specify tenth parameter
  196.          Push      AX                        ; Save on stack
  197.          Call      __ParNI                   ; Get light bar attribute
  198.          Add       SP,2                      ; Realign stack
  199.          LES       BX,[NodePtr]              ; Restore node pointer
  200.          Mov       [MenuItem.LBarAtt],AL     ; Store light bar attribute
  201.  
  202.          Mov       AX,11                     ; Specify eleventh parameter
  203.          Push      AX                        ; Save on stack
  204.          Call      __ParNI                   ; Get hotkey/lightbar attribute
  205.          Add       SP,2                      ; Realign stack
  206.          LES       BX,[NodePtr]              ; Restore node pointer
  207.          Mov       [MenuItem.LBHKAtt],AL     ; Store hotkey/lightbar attribute
  208.  
  209.          Mov       AX,12                     ; Specify twelfth parameter
  210.          Push      AX                        ; Save on stack
  211.          Call      __ParNI                   ; Get up arrow target
  212.          Add       SP,2                      ; Realign stack
  213.          LES       BX,[NodePtr]              ; Restore node pointer
  214.          Mov       [MenuItem.Up],AX          ; Store up arrow target
  215.  
  216.          Mov       AX,13                     ; Specify thirteenth parameter
  217.          Push      AX                        ; Save on stack
  218.          Call      __ParNI                   ; Get down arrow target
  219.          Add       SP,2                      ; Realign stack
  220.          LES       BX,[NodePtr]              ; Restore node pointer
  221.          Mov       [MenuItem.Down],AX        ; Store down arrow target
  222.  
  223.          Mov       AX,14                     ; Specify fourteenth parameter
  224.          Push      AX                        ; Save on stack
  225.          Call      __ParNI                   ; Get right arrow target
  226.          Add       SP,2                      ; Realign stack
  227.          LES       BX,[NodePtr]              ; Restore node pointer
  228.          Mov       [MenuItem.Right],AX       ; Store right arrow target
  229.  
  230.          Mov       AX,15                     ; Specify fifteenth parameter
  231.          Push      AX                        ; Save on stack
  232.          Call      __ParNI                   ; Get left arrow target
  233.          Add       SP,2                      ; Realign stack
  234.          LES       BX,[NodePtr]              ; Restore node pointer
  235.          Mov       [MenuItem.Left],AX        ; Store left arrow target
  236.  
  237.          Call      __Ret                     ; Return NIL
  238.          Mov       SP,BP                     ; Restore SP
  239.          Pop       BP                        ; Restore BP
  240.          Ret
  241. Endp     __ftprompt
  242.  
  243.  
  244.  
  245. Proc     _ftStrDup Near
  246.  
  247.          Push      BP                        ; Save BP
  248.          Mov       BP,SP                     ; Set up stack reference
  249.          Push      DS                        ; Save DS
  250.          Push      SI                        ; Save SI
  251.          Push      DI                        ; Save DI
  252.          CLD                                 ; Ensure forward movement
  253.  
  254.          Mov       SI,[Word Ptr BP + 4]      ; Get source offset
  255.          Mov       DS,[Word Ptr BP + 6]      ; Get source segment
  256.          Mov       DI,[Word Ptr BP + 8]      ; Get target offset
  257.          Mov       ES,[Word Ptr BP + 10]     ; Get target segment
  258.          Mov       CX,[Word Ptr BP + 12]     ; Get string length
  259.          Rep       Movsb                     ; Copy string
  260.  
  261.          Pop       DI                        ; Restore DI
  262.          Pop       SI                        ; Restore SI
  263.          Pop       DS                        ; Restore DS
  264.          Pop       BP                        ; Restore BP
  265.          Ret
  266. Endp     _ftStrDup
  267.  
  268.  
  269.  
  270. Proc     __ftMenuTo Far
  271.  
  272.          Push      BP                        ; Save BP
  273.          Mov       BP,SP                     ; Set up stack reference
  274.          Sub       SP,24                     ; Allocate space for locals
  275.  
  276.          Mov       BX,_MenuData              ; Get local data segment
  277.          Mov       ES,BX                     ; Load into segment register
  278.          Mov       BX,[ES:PrCount]           ; Get prompt count
  279.          Or        BX,BX                     ; Any prompts yet?
  280.          JNZ       Okay                      ; Yes, so continue
  281.          Mov       AX,BX                     ; Get low word of return value
  282.          Mov       DX,BX                     ; Get high word of return value
  283.          Jmp       Done                      ; Exit with return of zero
  284.  
  285. Okay:    Mov       [Last],BX                 ; Store prompt count in local
  286.          Mov       [NodeSeg],ES              ; Store current node pointer
  287.          Mov       [NodeOfs],Offset ES:HeadOfs - 38
  288.  
  289. GetDesiredPrompt:
  290.          Mov       AX,1                      ; Specify first param
  291.          Push      AX                        ; Put on stack
  292.          Call      __ParNI                   ; Get parameter
  293.          Add       SP,2                      ; Realign stack
  294.          Mov       CX,1                      ; Set default value
  295.          Or        AX,AX                     ; Specified prompt = 0?
  296.          JZ        SetActivePrompt           ; If so, use default
  297.          Cmp       AX,[Last]                 ; Check AX against prompt count
  298.          JA        SetActivePrompt           ; If higher, use default
  299.          Mov       CX,AX                     ; Value okay, so use it
  300.  
  301. SetActivePrompt:
  302.          Mov       [Active],CX               ; Initalize active prompt
  303.  
  304. GetFlagValues:
  305.          Mov       AX,2                      ; Specify second param
  306.          Push      AX                        ; Put on stack
  307.          Call      __ParNI                   ; Get parameter
  308.          Add       SP,2                      ; Realign stack
  309.          Mov       [Flags],AX                ; Store flags
  310.  
  311. GetSetKeyStuff:
  312.          Xor       AX,AX                     ; Request element count
  313.          Push      AX                        ; Put on stack
  314.          Mov       AX,3                      ; Specify third param
  315.          Push      AX                        ; Put on stack
  316.          Call      __ParInfa                 ; Get setkey count
  317.          Mov       [SKCount],AX              ; Store key count
  318.          SHL       AX,1                      ; Multiply by by two
  319.          Push      AX                        ; Put result on stack
  320.          Call      __XGrab                   ; Allocate scan code table
  321.          Add       SP,6                      ; Realign stack
  322.          Mov       [SKOfs],AX                ; Store offset
  323.          Mov       [SKSeg],DX                ; Store segment
  324.          Mov       CX,[SKCount]              ; Set loop value
  325.          JCXZ      CheckForColor             ; If no setkeys, skip next part
  326. GetNextScanCode:
  327.          Push      CX                        ; Put element # on stack
  328.          Mov       AX,3                      ; Specify third param
  329.          Push      AX                        ; Put on stack
  330.          Call      __ParNI                   ; Get scancode
  331.          Add       SP,2                      ; Realign stack
  332.          Pop       CX                        ; Restore CX
  333.          Mov       BX,CX                     ; Load element # into BX
  334.          Dec       BX                        ; Compensate for zero start
  335.          SHL       BX,1                      ; Multiply by two
  336.          Add       BX,[SKOfs]                ; Add offset
  337.          Mov       ES,[SKSeg]                ; Load segment
  338.          Mov       [Word Ptr ES:BX],AX       ; Store scancode
  339.          Loop      GetNextScanCode           ; Do the next one
  340.  
  341. CheckForColor:
  342.          Mov       [VideoBase],0B800h        ; Default to color
  343.          Xor       AX,AX                     ; Clear AX
  344.          Mov       ES,AX                     ; Point ES to low memory
  345.          Cmp       [Word Ptr ES:463h],3D4h   ; Color video?
  346.          JE        VideoTest                 ; If so, don't change to mono
  347.          Mov       [VideoBase],0B000h        ; Change video base to mono
  348.          And       [Flags],NOT SnowFlag      ; If mono, don't check for snow
  349.          Jmp       AllocateHotKeys           ; Allocate hotkey table
  350.  
  351. VideoTest:
  352.          Mov       AH,12h                    ; EGA/VGA BIOS call
  353.          Mov       BL,10h                    ; Set BL to test value
  354.          Int       10h                       ; Call video BIOS
  355.          Cmp       BL,10h                    ; Did BL change?
  356.          JE        AllocateHotKeys           ; No, so leave snow flag alone
  357.          And       [Flags],NOT SnowFlag      ; EGA/VGA, set snow flag to false
  358.  
  359. AllocateHotKeys:
  360.          Push      [Last]                    ; Put prompt count on stack
  361.          Call      __XGrab                   ; Allocate hotkey table
  362.          Add       SP,2                      ; Realign stack
  363.          Mov       [TableSeg],DX             ; Store segment
  364.          Mov       [TableOfs],AX             ; Store offset
  365.  
  366. MainLoopSetup:
  367.          Push      DS                        ; Save DS
  368.          Push      SI                        ; Save SI
  369.          Push      DI                        ; Save DI
  370.          CLD                                 ; Ensure forward movement
  371.  
  372.          Mov       DX,3DAh                   ; Specify status port for later
  373.          Mov       CX,[Last]                 ; Initalize loop register
  374.          LES       BX,[NodePtr]              ; Initialize ES:BX
  375.  
  376. PromptLoopTop:
  377.          Push      CX                        ; Save loop counter
  378.          LES       BX,[NextPtr]              ; Get pointer to next node
  379.          Mov       AL,[MenuItem.HKeyVal]     ; Get hotkey value
  380.          LDS       SI,[TablePtr]             ; Get pointer to hotkey table
  381.          Add       SI,CX                     ; Adjust offset
  382.          Mov       [Byte Ptr SI - 1],AL      ; Store hotkey value
  383.          LDS       SI,[PrPtr]                ; Get pointer to prompt
  384.          Mov       CX,[MenuItem.PrLen]       ; Get prompt length
  385.          JCXZ      PromptLoopBottom          ; If length = 0, jump to bottom
  386.          Mov       AH,[MenuItem.PrAtt]       ; Get prompt attribute
  387.          Push      ES                        ; Save ES
  388.          Mov       DI,[MenuItem.PrLoc]       ; Get screen location offset
  389.          Mov       ES,[VideoBase]            ; Get screen location segment
  390.  
  391. PromptRead:
  392.          Lodsb                               ; Get a prompt character
  393.          Test      [Flags],SnowFlag          ; See if snow-check in effect
  394.          JZ        PromptWrite               ; If not, continue
  395.          CheckSnow                           ; Wait for vertical retrace
  396.  
  397. PromptWrite:
  398.          Stosw                               ; Write character and attribute
  399.          Loop      PromptRead                ; Do next character
  400.          Pop       ES                        ; Restore ES
  401.  
  402. GetHotKeyAttr:
  403.          Push      ES                        ; Save ES again
  404.          Mov       DI,[MenuItem.HKeyLoc]     ; Get hotkey location
  405.          Inc       DI                        ; Select attribute byte
  406.          Mov       AL,[MenuItem.HKeyAtt]     ; Get hotkey attribute
  407.          Mov       ES,[VideoBase]            ; Get video base segment
  408.          Test      [Flags],SnowFlag          ; See if snow-check in effect
  409.          JZ        HotKeyAttr                ; If not, continue
  410.          CheckSnow                           ; Wait for vertical retrace
  411. HotKeyAttr:
  412.          Stosb                               ; Change attribute byte
  413.          Pop       ES                        ; Restore ES
  414.  
  415. PromptLoopBottom:
  416.          Pop       CX                        ; Restore loop counter
  417.          Loop      PromptLoopTop             ; Do next prompt
  418.  
  419. GetActivePrompt:
  420.          LES       BX,[NodePtr]              ; Get pointer to last node
  421.          Mov       AX,[Active]               ; Load current active item
  422.  
  423. SearchLinkedList:
  424.          LES       BX,[NextPtr]              ; Get pointer to next item
  425.          Cmp       AX,[MenuItem.PrNum]       ; Found it yet?
  426.          JNE       SearchLinkedList          ; Nope, so keep looking
  427.  
  428. LightBarStuff:
  429.          Push      ES                        ; Save ES
  430.          Mov       AL,[MenuItem.LBarAtt]     ; Get light bar attribute
  431.          Mov       CX,[MenuItem.PrLen]       ; Get prompt length
  432.          JCXZ      LightBarEnd               ; If length = 0, don't bother
  433.          Mov       DI,[MenuItem.PrLoc]       ; Get prompt location
  434.          Mov       ES,[VideoBase]            ; Load video base segment
  435. SetLightBarPtr:
  436.          Inc       DI                        ; Locate attribute byte
  437.          Test      [Flags],SnowFlag          ; Check for snow?
  438.          JZ        WriteLightBar             ; If not, continue
  439.          CheckSnow                           ; Wait for vertical retrace
  440. WriteLightBar:
  441.          Stosb                               ; Change attribute
  442.          Loop      SetLightBarPtr            ; Do next byte
  443. LightBarEnd:
  444.          Pop       ES                        ; Restore ES
  445.  
  446. GetLightBarHotKeyAttr:
  447.          Push      ES                        ; Save ES again
  448.          Mov       DI,[MenuItem.HKeyLoc]     ; Get hotkey location
  449.          Inc       DI                        ; Select attribute byte
  450.          Mov       AL,[MenuItem.LBHKAtt]     ; Get hotkey/lightbar attribute
  451.          Mov       ES,[VideoBase]            ; Get video base segment
  452.          Test      [Flags],SnowFlag          ; See if snow-check in effect
  453.          JZ        LightBarHotKeyAttr        ; If not, continue
  454.          CheckSnow                           ; Wait for vertical retrace
  455. LightBarHotKeyAttr:
  456.          Stosb                               ; Change attribute byte
  457.          Pop       ES                        ; Restore ES
  458.  
  459. BufferStuff:
  460.          Test      [Flags],SKFlag            ; Is setkey flag set?
  461.          JNZ       MessageStuff              ; If so, buffer already current
  462.          Push      ES                        ; Save ES
  463.          Mov       CX,[MenuItem.MsgLen]      ; Get message length
  464.          JCXZ      MessageEnd                ; If length = 0, don't bother
  465.          Mov       DS,[VideoBase]            ; Set DS to video RAM
  466.          Mov       SI,[MenuItem.MsgLoc]      ; Get message screen location
  467.          LES       DI,[BufPtr]               ; Get pointer to buffer
  468.          Test      [Flags],SnowFlag          ; Check for snow?
  469.          JZ        FastBuffer                ; If not, use fast method
  470. SlowBuffer:
  471.          CheckSnow                           ; Wait for vertical retrace
  472.          Movsw                               ; Store character and attribute
  473.          Loop      SlowBuffer                ; Do next character
  474. FastBuffer:
  475.          Rep       Movsw                     ; Store buffer
  476.          Pop       ES                        ; Restore ES
  477.  
  478. MessageStuff:
  479.          And       [Flags],NOT SKFlag        ; Turn setkey flag off
  480.          Push      ES                        ; Save ES
  481.          Mov       CX,[MenuItem.MsgLen]      ; Get message length
  482.          JCXZ      MessageEnd                ; If length = 0, no message
  483.          LDS       SI,[MsgPtr]               ; Get pointer to message
  484.          Mov       AH,[MenuItem.MsgAtt]      ; Get message attribute
  485.          Mov       DI,[MenuItem.MsgLoc]      ; Get message location
  486.          Mov       ES,[VideoBase]            ; Point ES to video RAM
  487. MessageRead:
  488.          Lodsb                               ; Get a message byte
  489.          Test      [Flags],SnowFlag          ; Check for snow?
  490.          JZ        MessageWrite              ; Skip snow check
  491.          CheckSnow                           ; Wait for vertical retrace
  492. MessageWrite:
  493.          Stosw                               ; Write char and attribute
  494.          Loop      MessageRead               ; Get next byte
  495. MessageEnd:
  496.          Pop       ES                        ; Restore ES
  497.  
  498. CheckForHotKey:
  499.          Test      [Flags],HotFlag           ; Hotkey pending?
  500.          JZ        GetNextKey                ; If not, get next key
  501.          Test      [Flags],ColdFlag          ; Hotkeys supposed to act cold?
  502.          JNZ       GetNextKey                ; If so, continue
  503.          Jmp       ExitWithSelection         ; We're finished
  504.  
  505. GetNextKey:
  506.          And       [Flags],NOT HotFlag       ; Make sure hotflag is off
  507.          Mov       AH,0                      ; BIOS service -- keyboard input
  508.          Int       16h                       ; Get a keystroke
  509.          Or        AL,AL                     ; Extended keystroke?
  510.          JZ        CheckForSetKey            ; If so, continue
  511.          Mov       AH,0                      ; Clear scan code -- ASCII in AL
  512.  
  513. CheckForSetKey:
  514.          Mov       [ScanCode],AX             ; Store most recent scancode
  515.          Mov       CX,[SKCount]              ; Get setkey count
  516.          JCXZ      CheckEscapeKey            ; If 0, no need for table check
  517.          Push      ES                        ; Save ES
  518.          LES       DI,[SetKeys]              ; Get pointer to setkey table
  519.          Repnz     Scasw                     ; Look for extended scan code
  520.          Pop       ES                        ; Restore ES
  521.          JNZ       CheckEscapeKey            ; Not found; check other keys
  522.          Or        [Flags],KeepFlag          ; Turn keep flag on
  523.          Jmp       ExitWithSelection         ; Go back to execute SET KEY
  524.  
  525. CheckEscapeKey:
  526.          Cmp       AL,27                     ; Escape key?
  527.          JNE       CheckEnterKey             ; If not, check for enter
  528.          Mov       [Active],0                ; Set return value
  529.          Jmp       ExitWithSelection         ; See if prompts need deallocated
  530.  
  531. CheckEnterKey:
  532.          Cmp       AL,13                     ; Enter key?
  533.          JNE       CheckUpLeftArrow          ; If not, check arrow keys
  534.          Jmp       ExitWithSelection         ; See if prompts need deallocated
  535.  
  536. CheckUpLeftArrow:
  537.          Mov       CX,[MenuItem.Up]          ; Get up arrow target
  538.          Cmp       AX,4800h                  ; Up arrow key?
  539.          JE        ProcessUpLeftArrow        ; If so, process it
  540.          Mov       CX,[MenuItem.Left]        ; Get left arrow target
  541.          Cmp       AX,4B00h                  ; Left arrow key?
  542.          JE        ProcessUpLeftArrow        ; If so, process it
  543.          Jmp       CheckDownRightArrow       ; Check for right or down arrow
  544. ProcessUpLeftArrow:
  545.          Or        CX,CX                     ; Default behavior requested?
  546.          JZ        UpLeftDefault             ; If so, go to previous prompt
  547.          Cmp       CX,[Last]                 ; Target beyond range?
  548.          JA        UpLeftDefault             ; If so, use default behavior
  549.          Jmp       GetNewPrompt              ; Get new prompt
  550. UpLeftDefault:
  551.          Mov       CX,[Active]               ; Load active prompt
  552.          Cmp       CX,1                      ; First prompt active?
  553.          JE        UpLeftWrap                ; If so, check for wrap
  554.          Dec       CX                        ; Decrement active prompt
  555.          Jmp       UpLeftExit                ; Exit
  556. UpLeftWrap:
  557.          Test      [Flags],WrapFlag          ; Wrapping requested?
  558.          JZ        UpLeftExit                ; If not, exit
  559.          Mov       CX,[Last]                 ; Wrap to last prompt
  560. UpLeftExit:
  561.          Jmp       GetNewPrompt              ; Get new prompt
  562.  
  563. CheckDownRightArrow:
  564.          Mov       CX,[MenuItem.Down]        ; Get down arrow target
  565.          Cmp       AX,5000h                  ; Down arrow key?
  566.          JE        ProcessRightDownArrow     ; If so, process it
  567.          Mov       CX,[MenuItem.Right]       ; Get right arrow target
  568.          Cmp       AX,4D00h                  ; Right arrow key?
  569.          JE        ProcessRightDownArrow     ; If so, process it
  570.          Jmp       CheckHotKeyTable          ; Check hotkey table
  571. ProcessRightDownArrow:
  572.          Or        CX,CX                     ; Default behavior requested?
  573.          JZ        DownRightDefault          ; If so, go to previous prompt
  574.          Cmp       CX,[Last]                 ; Target beyond range?
  575.          JA        DownRightDefault          ; If so, use default behavior
  576.          Jmp       GetNewPrompt              ; Get new prompt
  577. DownRightDefault:
  578.          Mov       CX,[Active]               ; Load active prompt
  579.          Cmp       CX,[Last]                 ; Last? prompt active?
  580.          JE        DownRightWrap             ; If so, check for wrap
  581.          Inc       CX                        ; Increment active prompt
  582.          Jmp       DownRightExit             ; Exit
  583. DownRightWrap:
  584.          Test      [Flags],WrapFlag          ; Wrapping requested?
  585.          JZ        DownRightExit             ; If not, exit
  586.          Mov       CX,1                      ; Wrap to last prompt
  587. DownRightExit:
  588.          Jmp       GetNewPrompt              ; Get new prompt
  589.  
  590. CheckHotKeyTable:
  591.          Push      ES                        ; Save ES
  592.          Cmp       AL,'a'                    ; Check for lowercase a
  593.          JB        LoadHotKeyTable           ; If below, don't convert
  594.          Cmp       AL,'z'                    ; Check for lowercase z
  595.          JA        LoadHotKeyTable           ; If above, don't convert
  596.          And       AL,0DFh                   ; Convert to uppercase
  597. LoadHotKeyTable:  
  598.          LES       DI,[TablePtr]             ; Get pointer to table
  599.          Add       DI,[Active]               ; Compensate for active prompt
  600.          Mov       CX,[Last]                 ; Get last prompt
  601.          Cmp       CX,[Active]               ; At last prompt now?
  602.          JE        TableWrap                 ; If so, need to wrap
  603.          Sub       CX,[Active]               ; # of prompts to end
  604.          Repne     Scasb                     ; Look for value
  605.          JNZ       TableWrap                 ; If not found, wrap to start
  606.          Pop       ES                        ; Restore ES
  607.          Sub       CX,[Last]                 ; Subtract prompt count
  608.          Jmp       EvaluateHotKey            ; Evaluate hotkey
  609. TableWrap:
  610.          LES       DI,[TablePtr]             ; Get pointer to table
  611.          Mov       CX,[Active]               ; Set CX to active prompt
  612.          Repne     Scasb                     ; Look for value
  613.          Pop       ES                        ; Restore ES
  614.          JNZ       KeepSamePrompt            ; Invalid key, get another one
  615.          Sub       CX,[Active]               ; Subtract prompt offset
  616. EvaluateHotKey:
  617.          Neg       CX                        ; Get absolute value
  618.          Or        [Flags],HotFlag           ; Turn hotflag on
  619.          Jmp       GetNewPrompt              ; Get new prompt
  620.  
  621. KeepSamePrompt:
  622.          Jmp       CheckForHotKey            ; Discard key and get another
  623.  
  624. GetNewPrompt:
  625.          Cmp       CX,[Active]               ; Prompt changed?
  626.          JE        KeepSamePrompt            ; If not, keep it
  627.  
  628.          Mov       [Active],CX               ; Set active prompt
  629.          Push      ES                        ; Save ES
  630.          Mov       AL,[MenuItem.PrAtt]       ; Get prompt attribute
  631.          Mov       CX,[MenuItem.PrLen]       ; Get prompt length
  632.          JCXZ      BarIsDead                 ; If length = 0, don't bother
  633.          Mov       DI,[MenuItem.PrLoc]       ; Get prompt location
  634.          Mov       ES,[VideoBase]            ; Load video base segment
  635. KillLightBar:
  636.          Inc       DI                        ; Locate attribute byte
  637.          Test      [Flags],SnowFlag          ; Check for snow?
  638.          JZ        ResetPromptAttr           ; If not, continue
  639.          CheckSnow                           ; Wait for vertical retrace
  640. ResetPromptAttr:
  641.          Stosb                               ; Change attribute
  642.          Loop      KillLightBar              ; Do next byte
  643.          Pop       ES                        ; Restore ES
  644.          Push      ES                        ; Save ES again
  645.          Mov       DI,[MenuItem.HKeyLoc]     ; Get hotkey location
  646.          Inc       DI                        ; Select attribute byte
  647.          Mov       AL,[MenuItem.HKeyAtt]     ; Get hotkey attribute
  648.          Mov       ES,[VideoBase]            ; Get video base segment
  649.          Test      [Flags],SnowFlag          ; See if snow-check in effect
  650.          JZ        ResetHotKeyAttr           ; If not, continue
  651.          CheckSnow                           ; Wait for vertical retrace
  652. ResetHotKeyAttr:
  653.          Stosb                               ; Change attribute byte
  654. BarIsDead:
  655.          Pop       ES                        ; Restore ES
  656.  
  657. KillMessage:
  658.          Push      ES                        ; Save ES
  659.          Mov       CX,[MenuItem.MsgLen]      ; Get message length
  660.          JCXZ      MessageIsDead             ; If length = 0, don't bother
  661.          LDS       SI,[BufPtr]               ; Get pointer to buffer
  662.          Mov       DI,[MenuItem.MsgLoc]      ; Get message screen location
  663.          Mov       ES,[VideoBase]            ; Set DS to video RAM
  664.          Test      [Flags],SnowFlag          ; Check for snow?
  665.          JZ        QuickDeath                ; If not, use fast method
  666. SlowDeath:
  667.          CheckSnow                           ; Wait for vertical retrace
  668.          Movsw                               ; Store character and attribute
  669.          Loop      SlowDeath                 ; Do next character
  670. QuickDeath:
  671.          Rep       Movsw                     ; Store buffer
  672. MessageIsDead:
  673.          Pop       ES                        ; Restore ES
  674.          Jmp       GetActivePrompt           ; Go to top of loop
  675.  
  676. Done:    Push      DX                        ; Put high word on stack
  677.          Push      AX                        ; Put low word on stack
  678.          Call      __RetNL                   ; Return value to app
  679.          Mov       SP,BP                     ; Restore SP
  680.          Pop       BP                        ; Restore BP
  681.          Ret
  682. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  683. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  684.  
  685.  
  686. ExitWithSelection:
  687.          Pop       DI                        ; Restore registers
  688.          Pop       SI
  689.          Pop       DS
  690.          Call      Near KillPrompts          ; Kill prompts if needed
  691.          Push      [TableSeg]                ; Hotkey table segment on stack
  692.          Push      [TableOfs]                ; HotKey table offset on stack
  693.          Call      __XFree                   ; Free allocated RAM
  694.          Push      [SKSeg]                   ; Scancode table segment on stack
  695.          Push      [SKOfs]                   ; Scancode table offset on stack
  696.          Call      __XFree                   ; Free allocated RAM
  697.          Mov       AX,[Active]               ; Set low order word
  698.          Mov       DX,[ScanCode]             ; Set high order word
  699.          Jmp       Done
  700.  
  701. KillPrompts:
  702.          Test      [Flags],KeepFlag          ; Supposed to keep prompts?
  703.          JZ        PromptDeallocSetup        ; If not, kill them
  704.          RetN                                ; Near return
  705.  
  706. PromptDeallocSetup:
  707.          LES       BX,[NodePtr]              ; Get first node pointer
  708.          Mov       CX,[Last]                 ; Get loop value
  709.          Mov       [ES:PrCount],0            ; Reset prompt counter
  710.          LES       BX,[NextPtr]              ; Get pointer to next item
  711.  
  712. KillAPrompt:
  713.          Mov       [NodeSeg],ES              ; Put ES:BX into local storage --
  714.          Mov       [NodeOfs],BX              ; saves pushing and popping
  715.          Push      [MenuItem.NextSeg]        ; Put next segment on stack
  716.          Push      [MenuItem.NextOfs]        ; Put next offset on stack
  717.  
  718.          Push      [MenuItem.PrSeg]          ; Put prompt segment on stack
  719.          Push      [MenuItem.PrOfs]          ; Put prompt offset on stack
  720.          Call      __XFree                   ; Free memory
  721.          LES       BX,[NodePtr]              ; Restore node pointer
  722.  
  723.          Push      [MenuItem.MsgSeg]         ; Put message segment on stack
  724.          Push      [MenuItem.MsgOfs]         ; Put message offset on stack
  725.          Call      __XFree                   ; Free memory
  726.          LES       BX,[NodePtr]              ; Restore node pointer
  727.  
  728.          Push      [MenuItem.BufSeg]         ; Put buffer segment on stack
  729.          Push      [MenuItem.BufOfs]         ; Put buffer offset on stack
  730.          Call      __XFree                   ; Free memory
  731.          LES       BX,[NodePtr]              ; Restore node pointer
  732.  
  733.          Push      ES                        ; Put node segment on stack
  734.          Push      BX                        ; Put node offset on stack
  735.          Call      __XFree                   ; Free memory
  736.          Add       SP,16                     ; Realign stack
  737.  
  738.          Pop       BX                        ; Get new node offset
  739.          Pop       ES                        ; Get new node segment
  740.          Loop      KillAPrompt               ; Kill next node
  741.          RetN                                ; Near return
  742.  
  743. Endp     __ftMenuTo
  744. Ends     _NanFor
  745. End
  746. 
  747.